package edu.tsinghua.ddb.site;

import java.io.FileOutputStream;
import java.rmi.RemoteException;
import java.util.Map;
import java.util.Map.Entry;

import com.sun.rowset.CachedRowSetImpl;

import edu.tsinghua.ddb.beans.QueryTree;
import edu.tsinghua.ddb.beans.Sqlet;
import edu.tsinghua.ddb.components.Addresser;
import edu.tsinghua.ddb.components.Dispatcher;
import edu.tsinghua.ddb.components.Localizer;
import edu.tsinghua.ddb.components.Optimizer;
import edu.tsinghua.ddb.components.SQLParser;
import edu.tsinghua.ddb.components.decomposer.Decomposer;
import edu.tsinghua.ddb.components.decomposer.DecomposerFactory;
import edu.tsinghua.ddb.data.LocalDataAccess;
import edu.tsinghua.ddb.dictionary.GD;
import edu.tsinghua.ddb.dictionary.GlobalDictionary;
import edu.tsinghua.ddb.main.console.MyLog;
import edu.tsinghua.ddb.util.Conf;
import edu.tsinghua.ddb.util.Event;
import edu.tsinghua.ddb.util.TicToc;

public class SiteImp extends BasicSite {
	private static final long serialVersionUID = -7633591654117719396L;

	public SiteImp(String siteName) throws RemoteException {
		super(siteName);
		super.startListeningRMI();
	}

	@Override
	public CachedRowSetImpl query(String sqlString) throws RemoteException {
		// Sqlet sqlet = SQLParser.parse(sqlString);
		// if (sqlet.getCommand() == Sqlet.select) {
		//
		// } else {
		//
		// }
		// Decomposer decomposer =
		// DecomposerFactory.createBy(sqlet.getCommand(),
		// sqlet.getStrategy());
		// //
		// QueryTree qt = decomposer.decompose(sqlet);
		// qt = pipeLine(qt);
		// Map<Site, Sqlet> works = Addresser.address(qt);
		// Dispatcher dispatcher = new Dispatcher(this);
		// return dispatcher.queryAll(works);
		return LocalDataAccess.query(sqlString);
	}

	@Override
	public int execute(String sqlString) throws RemoteException {
		// Sqlet sqlet = SQLParser.parse(sqlString);
		// GlobalDictionaryImp gd = GlobalDictionaryImp.getInstance();
		// switch (sqlet.getCommand()) {
		// case Sqlet.createdb:
		// gd.createDb(sqlet.getDatabase());
		// break;
		// case Sqlet.dropdb:
		// gd.dropDb(sqlet.getDatabase());
		// break;
		// case Sqlet.createtable:
		// gd.createTable(sqlet.getDatabase(), sqlet.getTable(),
		// sqlet.getCreateStmt());
		// break;
		// case Sqlet.droptable:
		// gd.dropTable(sqlet.getDatabase(), sqlet.getTable());
		// break;
		// }
		return LocalDataAccess.update(sqlString);
	}

	@Override
	public void ping(String from) throws RemoteException {
		// if (ttl == 0) {
		// // MyLog.info("hello");
		// } else {
		// for (int i = Conf.getInt("SiteCount"); i > 0; i--) {
		// String sitepbp = Conf.get("site" + i);
		// if (!sitepbp.equalsIgnoreCase(this.publishedPoint)) {
		// try {
		// Site s = SitePool.get("site" + i);
		// long t0 = System.currentTimeMillis();
		// s.ping();
		// t0 = System.currentTimeMillis() - t0;
		// MyLog.info("RTT(ms) between " + this + " and site" + i
		// + "(" + sitepbp + ") = " + t0);
		// } catch (java.rmi.ConnectException e) {
		// MyLog.debug(this + " can not connect to site" + i + "("
		// + sitepbp + ")");
		// } catch (Exception e) {
		// e.printStackTrace();
		// }
		// }
		// }
		// }
		try {
			String me = SitePool.me.getName();
			if (from.equalsIgnoreCase(me)) {
				for (Entry<Site, SiteAttributes> sa : SitePool.sAttrMap
						.entrySet()) {
					Site s = sa.getKey();
					TicToc.tic();
					try {
						s.ping(from);
						long l = TicToc.toc();
						MyLog.debug("RTT between " + this.getName() + " and "
								+ s.getName() + " = " + l);
						sa.getValue().rtt = l;
					} catch (java.rmi.ConnectException e) {

						MyLog.debug(this + " can not connect to "
								+ sa.getValue().name);
						Event.fire(Event.LOST_CONNECTION, sa.getValue().name);
					}
				}
			} else
				MyLog.info("ping from " + from);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private QueryTree pipeLine(QueryTree qt) {
		qt = Localizer.locate(qt);
		qt = Optimizer.optimize(qt);
		return qt;
	}

	@Override
	public void upload(byte[] cnt, String filePath) throws RemoteException {
		FileOutputStream fos;
		try {
			fos = new FileOutputStream(filePath);
			fos.write(cnt);
			fos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void updateGD(GlobalDictionary gd) throws RemoteException {
		GD.replace(gd);
	}
}
